// Playground - noun: a place where people can play

import Cocoa

var str = "Hello, playground"




func mul(d1: Double , d2 : Double) -> Double
{
    return d1 * d2
}

func add(d1: Double, d2: Double) -> Double
{
    return d1 + d2;
}

func preform (res: String ,d2: Double) ->Double
{
    return 0
}

let numbers = [1,2,3]
let doubledNumber = numbers.map{$0 * 2}

var doubledImperative: [Int] = []
for num in numbers
{
    doubledImperative.append(num * 2)
}

let number = Optional(888)
let transformedNumber = number.map { $0 % 2 == 0 }

let nilNumber: Int? = .None
let transformedNilNumber = nilNumber.map{$0 % 2 == 0}

//func map< U>(transformFunction: T -> U) -> Container<U>
class Box<T>
{
    let unbox: T
    init (_ value: T)
    {
        self.unbox = value
    }

}


enum Result<T>
{
    case Value(Box <T>)
    case Error(NSError)
}

func dataWithContentOfFile(file: String , encoding: NSStringEncoding) -> Result<NSData>
{
    var error: NSError?
    
    if let data = NSData(contentsOfFile: file, options: .allZeros, error: &error) {
        return .Value(Box(data))
    }
    
        return .Error(error!)
}

extension Result {
    func map<U>(f: T-> U) -> Result<U> {
        switch self {
        case let .Value(value):
            return Result<U>.Value(Box(f(value.unbox)))
        case let .Error(error):
            return Result<U>.Error(error)
        }
    }
}



func getData1(path: String)
{
    let data: Result<NSData> = dataWithContentOfFile(path , NSUTF8StringEncoding)
   let uppercaseContents: Result<String> = data.map { NSString(data: $0, encoding: NSUTF8StringEncoding)! }.map { $0.uppercaseString }
}

func getData2(path: String)
{
    let data: Result<NSData> = dataWithContentOfFile(path, NSUTF8StringEncoding)
    var stringContents: String?
    
    switch data {
    case let .Value(value):
        stringContents = NSString(data: value.unbox, encoding: NSUTF8StringEncoding)
    case let .Error(error):
        break
    }
    
    let uppercaseContents: String? = stringContents?.uppercaseString
    
}

extension Result {
    static func flatten<T>(result: Result<Result<T>>) -> Result<T> {
        switch result {
        case let .Value(innerResult):
            return innerResult.unbox
        case let .Error(error):
            return Result<T>.Error(error)
        }
    }
}

func test3(path: String)
{
    let data: Result<NSData> = dataWithContentOfFile(path, NSUTF8StringEncoding)
    
    let stringResult = Result<String>.flatten(data.map { (data: NSData) -> (Result<String>) in
        if let string = NSString(data: data, encoding: NSUTF8StringEncoding) {
            return Result.Value(Box(string))
        }else {
            return Result<String>.Error(NSError(domain: "com.javisoto.es.error_domain", code: 100, userInfo: nil))
        }
         })
}

extension Result
{
    func flatMap<U>(f: T -> Result<U>) -> Result<U> {
        return Result.flatten(map(f))
    }
}
// http://robnapier.net/maps?utm_content=buffer1e521&utm_medium=social&utm_source=twitter.com&utm_campaign=buffer
//other something talk about the map

let domains = ["apple.com","google.com","xiaoLong.com"]

var urls = [NSURL]()
for domain in domains {
    urls.append(NSURL(scheme: "http", host: domain, path: "/")! )
}

func map<T,U>(source: [T], transform: T -> U) -> [U] {
    var result = [U]()
    for element in source {
        result.append(transform(element))
    }
    
    return result;
}



// test map
let urls1 = map(domains, { NSURL(scheme: "http", host: $0, path: "/") })

let urls2 = domains.map{ NSURL(scheme: "http", host: $0, path: "/" ) }

// filter
func filter<T>(source: [T], includeElement: T -> Bool) -> [T] {
    var found = [T]()
    for value in source {
        if includeElement(value) {
            found.append(value)
        }
    }
    return found
}

// test filter
let values = [1 , 1, 2, NSNotFound, 3, 4]
var found = [Int]()
for value in values {
    if value != NSNotFound {
        found.append(value)
    }
}

let found1 = filter(values, { $0 != NSNotFound })
let found2 = values.filter{$0 != NSNotFound}


func map<T, U>(x: T?, f: T -> U) -> U? {
    switch x {
    case .Some(let value): return .Some(f(value))
    case .None: return .None
    }
}



//func embeddedURLs(text: String) -> [NSURL] {
//    return text
//        .componentsSeparatedByString(" ")
//        .filter{ $0.hasPrefix("http://") }
//        .map{ NSURL(string: $0) }
//}

//
//embeddedURLs("This text contains a link to http://www.apple.com and other stuff.")







